home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb / sprite / sun4_kgdb_remote.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-30  |  39.7 KB  |  1,579 lines

  1. /* Memory-access and commands for inferior process, for GDB.
  2.    Copyright (C)  1988 Free Software Foundation, Inc.
  3.  
  4. GDB is distributed in the hope that it will be useful, but WITHOUT ANY
  5. WARRANTY.  No author or distributor accepts responsibility to anyone
  6. for the consequences of using it or for whether it serves any
  7. particular purpose or works at all, unless he says so in writing.
  8. Refer to the GDB General Public License for full details.
  9.  
  10. Everyone is granted permission to copy, modify and redistribute GDB,
  11. but only under the conditions described in the GDB General Public
  12. License.  A copy of this license is supposed to have been given to you
  13. along with GDB so you can know your rights and responsibilities.  It
  14. should be in a file named COPYING.  Among other things, the copyright
  15. notice and this notice must be preserved on all copies.
  16.  
  17. In other words, go ahead and share GDB, but don't try to stop
  18. anyone else from sharing it farther.  Help stamp out software hoarding!
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <sprite.h>
  23. #include <signal.h>
  24. #include <sys/types.h>
  25. #include <sys/file.h>
  26. #include <errno.h>
  27. #include "kernel/machTypes.h"
  28.  
  29. #include "defs.h"
  30. #include "param.h"
  31. #include "frame.h"
  32. #include "inferior.h"
  33. #include "value.h"
  34. #include "expression.h"
  35. #include "wait.h"
  36. #include "sprite.h"
  37. #include "kernel/sun4.md/vmSunConst.h"
  38. #include "kernel/sun4.md/machConst.h"
  39. #include "kernel/sun4.md/dbg.h"
  40. #define NOGAP
  41.  
  42. /*
  43.  * Hostname of attached remote hosts.  Error otherwise.
  44.  */
  45.  
  46. char *hostName;
  47.  
  48. /*
  49.  * Useful macros
  50.  * ERROR_NO_ATTACHED_HOST - Remote an error and abort if no host is
  51.  *                currently attached.
  52.  * MARK_DISCONNECTED - Mark a host a disconnected and free up state.
  53.  */
  54.  
  55. #define ERROR_NO_ATTACHED_HOST \
  56.     if (!hostName) error("No machine attached.");
  57.  
  58. #define MARK_DISCONNECTED  {     \
  59.     initialized = 0;          \
  60.     inferior_pid = 0;        \
  61.     hostName = (char *) 0;     \
  62.     free(dataCache);      \
  63.     free(cacheInfo);      \
  64.     }
  65.  
  66.  
  67. static    int    initialized = 0; /* Set to true when remote connection is
  68.                   * initialized. */
  69.  
  70. /*
  71.  * Table mapping kernel exceptions into Unix signals.  
  72.  */
  73.  
  74. struct sig_mapping_struct {
  75.     char     *sig_name;    /* Print string for signal. */
  76.     int     dbgSig;     /* Boolean - A signal used by the debugger. */
  77.     int     unixSignal;     /* Unix signal equalient. */
  78. } sig_mapping[] =  {
  79. /* 0 */ { "Reset Trap", 0, SIGQUIT },
  80. /* 1 */ { "Instruction Fault", 0, SIGSEGV },
  81. /* 2 */ { "Illegal Instruction Fault", 0, SIGILL },
  82. /* 3 */ { "Privilege Instruction Fault", 0, SIGILL },
  83. /* 4 */ { "FPU Disabled Fault", 0, SIGFPE },
  84. /* 5 */ { "Window Overflow Fault", 0, SIGBUS },
  85. /* 6 */ { "Window Underflow Fault", 0, SIGBUS },
  86. /* 7 */ { "Memory Address Fault", 0, SIGSEGV },
  87. /* 8 */ { "FPU Exception Fault", 0, SIGFPE },
  88. /* 9 */ { "Data Fault",  0, SIGSEGV },
  89. /* 10 */ { "Tag Overflow Trap", 0, SIGSEGV },
  90. /* 11 */ { "Unknown Trap 11",  0, SIGSEGV },
  91. /* 12 */ { "Unknown Trap 12",  0, SIGSEGV },
  92. /* 13 */ { "Unknown Trap 13",  0, SIGSEGV },
  93. /* 14 */ { "Unknown Trap 14",  0, SIGSEGV },
  94. /* 15 */ { "Unknown Trap 15",  0, SIGSEGV },
  95. /* 16 */ { "Interrupt Trap",  0, SIGINT },
  96. /* 17 */ { "Level 1 Interrupt", 0, SIGINT },
  97. /* 18 */ { "Level 2 Interrupt", 0, SIGINT },
  98. /* 19 */ { "Level 3 Interrupt", 0, SIGINT },
  99. /* 20 */ { "Level 4 Interrupt", 0, SIGINT },
  100. /* 21 */ { "Level 5 Interrupt", 0, SIGINT },
  101. /* 22 */ { "Level 6 Interrupt", 0, SIGINT },
  102. /* 23 */ { "Level 7 Interrupt", 0, SIGINT },
  103. /* 24 */ { "Level 8 Interrupt", 0, SIGINT },
  104. /* 25 */ { "Level 9 Interrupt", 0, SIGINT },
  105. /* 26 */ { "Level 10 Interrupt", 0, SIGINT },
  106. /* 27 */ { "Level 11 Interrupt", 0, SIGINT },
  107. /* 28 */ { "Level 12 Interrupt", 0, SIGINT },
  108. /* 29 */ { "Level 13 Interrupt", 0, SIGINT },
  109. /* 30 */ { "Level 14 Interrupt", 0, SIGINT },
  110. /* 31 */ { "Level 15 Interrupt", 0, SIGINT },
  111. /* 32 */ { "Breakpoint Trap",  1, SIGTRAP },
  112. /* 33 */ { "Unknown Trap",  0, SIGSEGV },
  113. /* 34 */ { "UNKNOWN EXCEPTION", 0, SIGSEGV },
  114. };
  115.  
  116. #define    NUM_SIG_MAPS    (sizeof(sig_mapping)/sizeof(sig_mapping[0]))
  117.  
  118.  
  119.  
  120. #define    PBUFSIZ    1024
  121.  
  122. /* Maximum number of bytes to read/write at once.  The value here
  123.    is chosen to fill up a packet (the headers account for the 32).  */
  124. #define MAXBUFBYTES ((PBUFSIZ-32)/2)
  125.  
  126.  
  127. /*
  128.  *----------------------------------------------------------------------
  129.  *
  130.  * Regnum_to_index --
  131.  *
  132.  *    Function mapping a gdb register number into an index.
  133.  *
  134.  * Results:
  135.  *    Index to Mach_State structure when treated as an array on ints.
  136.  *
  137.  * Side effects:
  138.  *    None.
  139.  *
  140.  *----------------------------------------------------------------------
  141.  */
  142. static int 
  143. Regnum_to_index(r) 
  144.     int    r;
  145. #define    O(f)    ((int)&(((Mach_RegState *) 0)->f)/sizeof(int))
  146.   if (r < 8) return O(globals[r]);
  147.   if (r < 16) return  O(ins[r-8]);
  148.   if (r < 32) return (r - 16);
  149.   if (r == Y_REGNUM) return O(y);
  150.   if (r == PS_REGNUM) return O(curPsr);
  151.   if (r == PC_REGNUM) return O(pc);
  152.   if (r == NPC_REGNUM) return O(nextPc);
  153.   return -1;
  154. #undef O
  155. };
  156. static int lastPid = -1;    /* Process ID of process being examined. -1
  157.                  * means process causing trap. */
  158.  
  159. /*
  160.  * The following variables are sued when using the core memory interface
  161.  * rather than active ethernet debugging.
  162.  */
  163. static int remoteCoreChan = -1;    /* Open file descriptor of core file. -1 
  164.                  * means no file open. */
  165. static char *remoteCoreFile;    /* Malloced name of core file. */
  166. static int remoteOffset;    /* Offset used to convert addresses to 
  167.                  * offsets into core file. */
  168. static StopInfo    remoteStopInfo;    /* Current Dbg_StopInfo from core file. */
  169. static Dbg_DumpBounds remoteBounds;  /* Dump bounds from core file. */
  170.  
  171. /*
  172.  * IN_CORE_FILE - Returns TRUE if address is in the corefile.
  173.  */
  174. #define    IN_CORE_FILE(addr) ((addr) >= (CORE_ADDR) remoteBounds.kernelCodeStart\
  175.       && ((addr) < (CORE_ADDR) remoteBounds.fileCacheStart + \
  176.                           remoteBounds.fileCacheSize))
  177.  
  178. /*
  179.  *----------------------------------------------------------------------
  180.  *
  181.  * coreSeek -
  182.  *
  183.  *    Finds address in core file and seeks to it.
  184.  *
  185.  * Results:
  186.  *    None.
  187.  *
  188.  * Side effects:
  189.  *    None.
  190.  *
  191.  *----------------------------------------------------------------------
  192.  */
  193. static int
  194. coreSeek(file, addr, whence)
  195.      int file;
  196.      CORE_ADDR addr;
  197.      int whence;
  198. {
  199.   if ((int)addr > (remoteBounds.kernelCodeStart + remoteBounds.kernelCodeSize)) {
  200.     if ((int)addr < remoteBounds.kernelDataStart) {
  201.       return -1;
  202.     }
  203.     else if ((int)addr > (remoteBounds.kernelDataStart + remoteBounds.kernelDataSize)) {
  204.       if ((int)addr < remoteBounds.kernelStacksStart) {
  205.     return -1;
  206.       }
  207.       else if ((int)addr > (remoteBounds.kernelStacksStart + remoteBounds.kernelStacksSize)) {
  208.     if ((int)addr < remoteBounds.fileCacheStart) {
  209.       return -1;
  210.     }
  211.     else {
  212.       lseek(file, addr - remoteBounds.fileCacheStart 
  213.         + sizeof(remoteStopInfo) + sizeof(remoteBounds)
  214.         + remoteBounds.kernelCodeSize + remoteBounds.kernelDataSize
  215.         + remoteBounds.kernelStacksSize, whence);
  216.     }
  217.       }
  218.       else {
  219.     lseek(file, addr - remoteBounds.kernelStacksStart
  220.           + sizeof(remoteStopInfo) + sizeof(remoteBounds)
  221.           + remoteBounds.kernelCodeSize + remoteBounds.kernelDataSize,
  222.           whence);
  223.       }
  224.     }
  225.     else {
  226.       lseek(file, addr - remoteBounds.kernelDataStart
  227.         + sizeof(remoteStopInfo) + sizeof(remoteBounds)
  228.         + remoteBounds.kernelCodeSize, whence);
  229.     }
  230.   }
  231.   else {
  232.     lseek(file, addr - remoteOffset, whence);
  233.   }
  234. }
  235.  
  236.  
  237. /*
  238.  *----------------------------------------------------------------------
  239.  *
  240.  * remote_core_file_command --
  241.  *
  242.  *    kgdb.sun4 core_file command.
  243.  *
  244.  * Results:
  245.  *    None.
  246.  *
  247.  * Side effects:
  248.  *    None.
  249.  *
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. void
  254. remote_core_file_command (filename, from_tty)
  255.      char *filename;
  256.      int from_tty;
  257. {
  258.   /* Discard all vestiges of any previous core file
  259.      and mark data and stack spaces as empty.  */
  260.  
  261.   if (remoteCoreFile)
  262.     free (remoteCoreFile);
  263.   remoteCoreFile = 0;
  264.  
  265.   if (remoteCoreChan >= 0)
  266.     close (remoteCoreChan);
  267.   remoteCoreChan = -1;
  268.   if (filename == 0) {
  269.     printf ("Corefile cleared.\n");
  270.     return;
  271.   }
  272.  
  273.   filename = tilde_expand (filename);
  274.   make_cleanup (free, filename);
  275.  
  276.   remoteCoreChan = open (filename, O_RDONLY, 0);
  277.   if (remoteCoreChan < 0)
  278.     perror_with_name (filename);
  279.  
  280.   {
  281.     /*
  282.      * Read the StopInfo and bounds and start the debugging session.
  283.      */
  284.     int val;
  285.     val = myread (remoteCoreChan, &remoteStopInfo, sizeof remoteStopInfo);
  286.     if (val < 0)
  287.       perror_with_name (filename);
  288.     val = myread (remoteCoreChan, &remoteBounds, sizeof remoteBounds);
  289.     if (val < 0)
  290.       perror_with_name (filename);
  291.     remote_debugging = 1;
  292.     remoteOffset = remoteBounds.kernelCodeStart - sizeof(remoteStopInfo) -
  293.             sizeof(remoteBounds);
  294.     start_remote();
  295.   }
  296. }
  297.  
  298. /* Open a connection to a remote debugger.
  299.    NAME is the filename used for communication.  */
  300.  
  301. void
  302. remote_open (name, from_tty)
  303.      char *name;
  304.      int from_tty;
  305. {
  306.   if (remoteCoreChan >= 0) {
  307.       error("Can't attach a machine when using a corefile\n");
  308.       return;
  309.   }
  310.  
  311.   hostName = savestring(name,strlen(name));
  312.   if (from_tty)
  313.     printf ("Remote debugging using %s\n", name);
  314.   remote_debugging = 1;
  315. }
  316.  
  317. char *
  318. remote_version()
  319. {
  320.   static char    version[1024];
  321.  
  322.   ERROR_NO_ATTACHED_HOST;
  323.   Kdbx_Trace(DBG_GET_VERSION_STRING, 0, version, 1024);
  324.   return version;
  325. }
  326.  
  327.  
  328.  
  329. /* Tell the remote machine to resume.  */
  330.  
  331. int     step_addr, step_addr_contents[2];
  332.  
  333. int
  334. remote_resume (step, signal)
  335.      int step, signal;
  336. {
  337.  
  338.   ERROR_NO_ATTACHED_HOST;
  339.   step_addr = -2;
  340.   if (step) {
  341.          static char break_insn[] = BREAKPOINT;
  342.          step_addr = read_register(NPC_REGNUM);
  343.          if ((remote_read_bytes(step_addr,step_addr_contents,8) != 0) ||
  344.          (remote_write_bytes(step_addr,break_insn, 4) != 0) ||
  345.          (remote_write_bytes(step_addr+4,break_insn, 4) != 0)) {
  346.          error("Can't set single step breakpoint at 0x%x\n", step_addr);
  347.       }
  348.  
  349.   }
  350.   if (Kdbx_Trace( DBG_CONTINUE, 0, 0, sizeof(int)) < 0) {
  351.         error("error trying to continue process\n");
  352.   }
  353.  
  354. }
  355.  
  356. /* Wait until the remote machine stops, then return,
  357.    storing status in STATUS just as `wait' would.  */
  358.  
  359. int
  360. remote_wait (status)
  361.      WAITTYPE *status;
  362. {
  363.     StopInfo    stopInfo;
  364.     int        trap;
  365.     int    text_size;
  366.     extern CORE_ADDR text_start, text_end;
  367.     if (remoteCoreChan >= 0) {
  368.     /*
  369.      * Debugging using core file, just set text_{start, end} and
  370.      * returned stopped signal.
  371.      */
  372.     status->w_status = 0;
  373.     status->w_stopval = WSTOPPED;
  374.     trap = DBG_CVT_MACH_TRAP(remoteStopInfo.trapType);
  375.     status->w_stopsig = sig_mapping[trap].unixSignal;
  376.     if ((lastPid == -1) && !sig_mapping[trap].dbgSig) { 
  377.         printf("Kernel returns with signal (%d) %s\n",
  378.             remoteStopInfo.trapType,
  379.             sig_mapping[trap].sig_name);
  380.     }
  381.     text_start = remoteBounds.kernelCodeStart;
  382.     text_end = remoteBounds.kernelCodeStart + remoteBounds.kernelCodeSize;
  383.     return status->w_stopsig;
  384.     }
  385.     ERROR_NO_ATTACHED_HOST;
  386.  
  387.     if (Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  388.                sizeof(stopInfo)) != 0) {
  389.     error("Can't get stop info\n");
  390.     }
  391.  
  392.     if (stopInfo.regs.pc == step_addr ||
  393.     stopInfo.regs.pc == step_addr+4) {
  394.          if (remote_write_bytes(step_addr,step_addr_contents, 8) != 0) 
  395.          error("Can't restore single step address\n");
  396.     }
  397.     status->w_status = 0;
  398.     status->w_stopval = WSTOPPED;
  399.  
  400.     trap = DBG_CVT_MACH_TRAP(stopInfo.trapType);
  401.     status->w_stopsig = sig_mapping[trap].unixSignal;
  402.     if ((lastPid != -1) && !sig_mapping[trap].dbgSig) { 
  403.     printf("Kernel returns with signal (%d) %s\n",stopInfo.trapType,
  404.         sig_mapping[trap].sig_name);
  405.     }
  406.  
  407.     text_size = text_end - text_start;
  408.     text_size &= ~(8*1024-1);
  409.     text_start = stopInfo.codeStart - 8*1024;
  410.     text_end = text_start+text_size;
  411.     return status->w_stopsig;
  412. }
  413.  
  414. /* Read the remote registers into the block REGS.  */
  415. #define FIRST_LOCAL_REGNUM    16
  416. void
  417. remote_fetch_registers (regs)
  418.      char *regs;
  419. {
  420.   StopInfo    stopInfo;
  421.   if (remoteCoreChan >= 0) {
  422.  
  423.       bcopy(remoteStopInfo.regs.globals,regs,4*8);
  424.       bcopy(remoteStopInfo.regs.ins,regs+4*8,4*8);
  425.       ((int *)regs)[Y_REGNUM] = remoteStopInfo.regs.y; 
  426.       ((int *)regs)[PS_REGNUM] = remoteStopInfo.regs.curPsr; 
  427.       ((int *)regs)[PC_REGNUM] = remoteStopInfo.regs.pc; 
  428.       ((int *)regs)[NPC_REGNUM] = remoteStopInfo.regs.nextPc; 
  429.       remote_read_bytes(remoteStopInfo.regs.ins[6], 
  430.             ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  431.       return;
  432.   }
  433.   ERROR_NO_ATTACHED_HOST;
  434.   Kdbx_Trace(DBG_GET_STOP_INFO, (char *) 0, (char *)&stopInfo,
  435.                sizeof(stopInfo));
  436.   bcopy(stopInfo.regs.globals,regs,4*8);
  437.   bcopy(stopInfo.regs.ins,regs+4*8,4*8);
  438.   ((int *)regs)[Y_REGNUM] = stopInfo.regs.y; 
  439.   ((int *)regs)[PS_REGNUM] = stopInfo.regs.curPsr; 
  440.   ((int *)regs)[PC_REGNUM] = stopInfo.regs.pc; 
  441.   ((int *)regs)[NPC_REGNUM] = stopInfo.regs.nextPc; 
  442.   remote_read_bytes(stopInfo.regs.ins[6], 
  443.         ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  444.  
  445. }
  446.  
  447.  
  448. int
  449. remote_attach(pid)
  450.     int    pid;
  451. {
  452.     int    status;
  453.     struct expression *expr;
  454.     register struct cleanup *old_chain;
  455.     register value val;
  456.     int    machRegStateAddr;
  457.     Proc_ControlBlock    *procPtr;
  458.     Mach_RegState machRegState;
  459.     char    exp[128];
  460.  
  461.     if (remoteCoreChan >= 0) {
  462.     if (pid != lastPid) {
  463.       /*
  464.        * Switching to a new process. 
  465.        */
  466.       if (pid == -1) {
  467.           /*
  468.            * Process -1 is the trap process. Whose stop info is 
  469.            * in the beginning of the corefile.
  470.            */
  471.           if (lseek(remoteCoreChan, 0, L_SET) < 0) {
  472.           error("lseek corefile");
  473.           return 0;
  474.            }
  475.           if (myread(remoteCoreChan, &remoteStopInfo, 
  476.             sizeof(remoteStopInfo)) < 0) {
  477.           error("read corefile");
  478.           return 0;
  479.           }
  480.           lastPid = pid;
  481.           start_remote();
  482.           return 1;
  483.       }
  484.       /*
  485.        * Lookup the switch regs of the specified process.
  486.        * They are in proc_PCBTable[pidSlot]->machStatePtr->switchRegs.
  487.        */
  488.       sprintf(exp,"proc_PCBTable[%d]", pid & 0xff);
  489.       expr = parse_c_expression (exp);
  490.       old_chain = make_cleanup (free_current_contents, &expr);
  491.  
  492.       val = evaluate_expression (expr);
  493.       do_cleanups (old_chain);
  494.       if ((value_as_long(val) == NIL) || (value_as_long(val) == 0)) {
  495.           error("Pid 0x%x does not have a control block\n", pid);
  496.       }
  497.       sprintf(exp,"proc_PCBTable[%d]->machStatePtr->switchRegs", pid & 0xff);
  498.       expr = parse_c_expression (exp);
  499.       old_chain = make_cleanup (free_current_contents, &expr);
  500.       val = evaluate_expression (expr);
  501.       do_cleanups (old_chain);
  502.       machRegStateAddr = value_as_long(val);
  503.       if (remote_read_bytes(machRegStateAddr, &machRegState, 
  504.             sizeof(Mach_RegState)) != 0) {
  505.         error("Can't read  regs from address 0x%x\n", machRegStateAddr);
  506.       }
  507.       remoteStopInfo.regs = machRegState;
  508.       /*
  509.        * The PC that is stored for a switch registers from on the
  510.        * sun4 is bogus.  We set the PC to be inside Mach_ContextSwitch.
  511.        */
  512.       strcpy(exp,"&Mach_ContextSwitch");
  513.       expr = parse_c_expression (exp);
  514.       old_chain = make_cleanup (free_current_contents, &expr);
  515.       val = evaluate_expression (expr);
  516.       do_cleanups (old_chain);
  517.       remoteStopInfo.regs.pc = value_as_long(val)+16;
  518.       remoteStopInfo.regs.nextPc = remoteStopInfo.regs.pc+4;
  519.       lastPid = pid;
  520.     }
  521.     start_remote();
  522.     return 1;
  523.     }
  524.     ERROR_NO_ATTACHED_HOST;
  525.     if (pid != lastPid) {
  526.     Kdbx_Trace(DBG_SET_PID, &pid, 0,sizeof(int));
  527.     lastPid = pid;
  528.     }
  529.     start_remote();
  530.     return 1;
  531. }
  532. int
  533. remote_detach(sig)
  534.     int    sig;
  535. {
  536.   int cur_pc;
  537.  
  538.   ERROR_NO_ATTACHED_HOST;
  539.   cur_pc = read_pc();
  540.   if (sig) 
  541.       Kdbx_Trace(DBG_DETACH, &cur_pc, 0, sizeof(int));
  542.   remote_clean_up();
  543.   return 0;
  544. }
  545.  
  546.  
  547.  
  548. /* Read a word from remote address ADDR and return it.
  549.    This goes through the data cache.  */
  550.  
  551. int
  552. remote_fetch_word (addr)
  553.      CORE_ADDR addr;
  554. {
  555.  
  556.   int buffer;
  557.   extern CORE_ADDR text_start, text_end;
  558.  
  559.   if (remoteCoreChan >= 0) {
  560.       if (IN_CORE_FILE(addr)) {
  561. #ifndef NOGAP
  562.       if (lseek(remoteCoreChan, addr - remoteOffset, L_SET) < 0) {
  563. #else
  564.       if (coreSeek(remoteCoreChan, addr, L_SET) < 0) {
  565. #endif
  566.           perror("lseek corefile");
  567.           errno = EIO;
  568.           return 0;
  569.        }
  570.       if (myread(remoteCoreChan, &buffer, sizeof(buffer)) < 0) {
  571.           perror("read corefile");
  572.           errno = EIO;
  573.           return 0;
  574.       }
  575.       } else {
  576.       /* fprintf(stderr, "Address 0x%x out of range\n", addr); */
  577.       errno = EIO;
  578.       return 0;
  579.       }
  580.       return buffer;
  581.   }
  582.  
  583.   ERROR_NO_ATTACHED_HOST;
  584.   if (addr >= text_start && addr < text_end)
  585.     {
  586.      if (Kdbx_Trace(DBG_INST_READ, addr, &buffer, sizeof(int)) != 0) {
  587.         errno = EIO;
  588.         return 0;
  589.      }
  590.      return buffer;
  591.     }
  592.   if (Kdbx_Trace(DBG_DATA_READ, addr, &buffer, sizeof(int)) != 0) {
  593.     errno = EIO;
  594.     return 0;
  595.   }
  596.   return buffer;
  597. }
  598.  
  599. /* Write a word WORD into remote address ADDR.
  600.    This goes through the data cache.  */
  601.  
  602. void
  603. remote_store_word (addr, word)
  604.      CORE_ADDR addr;
  605.      int word;
  606. {
  607.   extern CORE_ADDR text_start, text_end;
  608.   ERROR_NO_ATTACHED_HOST;
  609.   if (addr >= text_start && addr < text_end)
  610.     {
  611.       if (Kdbx_Trace(DBG_INST_WRITE, &word, addr, sizeof(word))!= 0) {
  612.         errno = EIO;
  613.         }
  614.         return;
  615.     }
  616.   if ( Kdbx_Trace(DBG_DATA_WRITE,  &word, addr, sizeof(word)) != 0) {
  617.      errno = EIO;
  618.   }
  619.   return;
  620. }
  621.  
  622. /* Write memory data directly to the remote machine.
  623.    This does not inform the data cache; the data cache uses this.
  624.    MEMADDR is the address in the remote memory space.
  625.    MYADDR is the address of the buffer in our space.
  626.    LEN is the number of bytes.  */
  627.  
  628. int
  629. remote_write_bytes (memaddr, myaddr, len)
  630.      CORE_ADDR memaddr;
  631.      char *myaddr;
  632.      int len;
  633. {
  634.   extern CORE_ADDR text_start, text_end;
  635.   ERROR_NO_ATTACHED_HOST;
  636.   if (memaddr >= text_start && memaddr < text_end)
  637.     {
  638.       return Kdbx_Trace(DBG_INST_WRITE, myaddr, memaddr, len);
  639.     }
  640.   return Kdbx_Trace(DBG_DATA_WRITE,  myaddr, memaddr, len);
  641. }
  642.  
  643. /* Read memory data directly from the remote machine.
  644.    This does not use the data cache; the data cache uses this.
  645.    MEMADDR is the address in the remote memory space.
  646.    MYADDR is the address of the buffer in our space.
  647.    LEN is the number of bytes.  */
  648.  
  649. int
  650. remote_read_bytes (memaddr, myaddr, len)
  651.      CORE_ADDR memaddr;
  652.      char *myaddr;
  653.      int len;
  654. {
  655.     int err;
  656.  
  657.   if (remoteCoreChan >= 0) {
  658.       if (IN_CORE_FILE(memaddr)) {
  659. #ifndef NOGAP
  660.       if (lseek(remoteCoreChan, memaddr - remoteOffset, L_SET) < 0) {
  661. #else
  662.       if (coreSeek(remoteCoreChan, memaddr, L_SET) < 0) {
  663. #endif
  664.           err = errno;
  665.           perror("lseek corefile");
  666.           return err;
  667.        }
  668.       if (myread(remoteCoreChan,myaddr, len) != len) {
  669.           err = errno;
  670.           perror("read corefile");
  671.           return (err > 0) ? err : 1;
  672.       }
  673.     } else {
  674.       /* fprintf(stderr, "Address 0x%x out of range\n", memaddr); */
  675.       return EIO;
  676.     }
  677.     return 0;
  678.   }
  679.   ERROR_NO_ATTACHED_HOST;
  680.   return Kdbx_Trace(DBG_DATA_READ, memaddr, myaddr, len);
  681. }
  682.  
  683. /* Read LEN bytes from inferior memory at MEMADDR.  Put the result
  684.    at debugger address MYADDR.  Returns errno value.  */
  685. int
  686. remote_read_inferior_memory(memaddr, myaddr, len)
  687.      CORE_ADDR memaddr;
  688.      char *myaddr;
  689.      int len;
  690. {
  691.   int xfersize, err;
  692.   while (len > 0)
  693.     {
  694.       if (len > MAXBUFBYTES)
  695.     xfersize = MAXBUFBYTES;
  696.       else
  697.     xfersize = len;
  698.  
  699.       err = remote_read_bytes (memaddr, myaddr, xfersize);
  700.       if (err != 0) 
  701.       return err;
  702.       memaddr += xfersize;
  703.       myaddr  += xfersize;
  704.       len     -= xfersize;
  705.     }
  706.   return 0; /* no error */
  707. }
  708.  
  709. /* Copy LEN bytes of data from debugger memory at MYADDR
  710.    to inferior's memory at MEMADDR.  Returns errno value.  */
  711. int
  712. remote_write_inferior_memory (memaddr, myaddr, len)
  713.      CORE_ADDR memaddr;
  714.      char *myaddr;
  715.      int len;
  716. {
  717.   int xfersize;
  718.   int err;
  719.   while (len > 0)
  720.     {
  721.       if (len > MAXBUFBYTES)
  722.     xfersize = MAXBUFBYTES;
  723.       else
  724.     xfersize = len;
  725.  
  726.       err = remote_write_bytes(memaddr, myaddr, xfersize);
  727.       if (err != 0) {
  728.     return err;
  729.       }
  730.  
  731.       memaddr += xfersize;
  732.       myaddr  += xfersize;
  733.       len     -= xfersize;
  734.     }
  735.   return 0; /* no error */
  736. }
  737.  
  738. /* Store the remote registers from the contents of the block REGS.  */
  739.  
  740. void
  741. remote_store_registers (regs,regno)
  742.      char *regs;
  743.      int    regno;
  744. {
  745.     int    i;
  746.  
  747.   ERROR_NO_ATTACHED_HOST;
  748.     if (regno < 0) { 
  749.     remote_write_bytes(((int *) regs)[SP_REGNUM], 
  750.                 ((int *) regs) + FIRST_LOCAL_REGNUM,4*16);
  751.     for (i = 0; i < 16; i++) {
  752.         Kdbx_Trace(DBG_WRITE_REG, &(((int *)regs)[i]),
  753.                     Regnum_to_index(i),sizeof(int));
  754.     }    
  755.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+Y_REGNUM,
  756.             Regnum_to_index(Y_REGNUM),sizeof(int));
  757.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+PC_REGNUM,
  758.             Regnum_to_index(PC_REGNUM),sizeof(int));
  759.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+NPC_REGNUM,
  760.             Regnum_to_index(NPC_REGNUM),sizeof(int));
  761.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+PS_REGNUM,
  762.             Regnum_to_index(PS_REGNUM),sizeof(int));
  763.  
  764.     } else {
  765.        int    ind = Regnum_to_index(regno);
  766.        if (ind >= 0) 
  767.        Kdbx_Trace(DBG_WRITE_REG, ((int *)regs)+regno,ind,sizeof(int));
  768.        else
  769.         remote_write_bytes(((int *) regs)[SP_REGNUM], 
  770.             ((int *) regs) + regno,4);
  771.     }
  772. }
  773.  
  774. /* 
  775.  * Call a remote function.
  776.  */
  777. call_remote_function(funaddr,nargs,numBytes,argBuffer)
  778.     CORE_ADDR funaddr;
  779.     int        nargs;
  780.     int        numBytes;
  781.     char    *argBuffer;
  782. {
  783.   int    returnValue;
  784.   ERROR_NO_ATTACHED_HOST;
  785.   Kdbx_Trace(DBG_BEGIN_CALL, (char *)0, (char *)0, 0);  
  786.   returnValue = Kdbx_Trace(DBG_CALL_FUNCTION,argBuffer,funaddr,numBytes);
  787.   Kdbx_Trace(DBG_END_CALL, (char *)0, (char *)0, 0);       
  788.   return returnValue;
  789. }
  790.  
  791. void
  792. remote_reboot (args)
  793.      char *args;
  794. {
  795.  
  796.   ERROR_NO_ATTACHED_HOST;
  797.   if (!args)
  798.     args = "";
  799.  
  800.   Kdbx_Trace(DBG_REBOOT, args, NULL, strlen(args));
  801. }
  802.  
  803.  
  804. #include <sys/types.h>
  805. #include <sys/socket.h>
  806. #include <sys/time.h>
  807. #include <netinet/in.h>
  808. #include <netdb.h>
  809. #include <sgtty.h>
  810.  
  811. /*
  812.  * Direct mapped cache of data and code.   The cache is flushed after every
  813.  * step and continue by incrementing the version number.  Flushing code
  814.  * isn't necessary but since kdbx already has an internal code cache it
  815.  * doesn't hurt and makes life easier.
  816.  */
  817. static    int    cacheBlockSize = -1;
  818. static    int    cacheBlockShift = -1;
  819. static    int    cacheSize = 128 * 1024;
  820. #define    CACHE_BLOCK_MASK     (cacheSize / cacheBlockSize - 1)
  821. #define    CACHE_BLOCK_OFFSET_MASK    (cacheBlockSize - 1)
  822. #define    NUM_CACHE_BLOCKS    (cacheSize >> cacheBlockShift)
  823. #define    CACHE_OFFSET_MASK    (cacheSize - 1)
  824. #define    GET_CACHE_BLOCK(address) (((unsigned int) address) >> cacheBlockShift)
  825. /*
  826.  * The data cache is just an array of characters.
  827.  */
  828. static    char    *dataCache;
  829. /*
  830.  * There is information about kept about each cache block.
  831.  */
  832. typedef    struct {
  833.     int        version;    /* Version number of this cache block. */
  834.     char    *realAddr;    /* Actual address of data stored in the block.*/
  835. } CacheInfo;
  836. static CacheInfo    *cacheInfo;
  837. static int    currentVersion = 1;
  838.  
  839. /*
  840.  * Stuff for the serial port.
  841.  */
  842. static    int    kernChannel = 0;
  843.  
  844.  
  845. /*
  846.  * Message buffers.
  847.  */
  848. static Dbg_Msg    msg;
  849. static int    msgSize;
  850. #define    REPLY_BUFFER_SIZE    16384
  851. static    char    replyBuffer[REPLY_BUFFER_SIZE];
  852. static    char    requestBuffer[DBG_MAX_REQUEST_SIZE];
  853. static    int    msgNum = 0;
  854.  
  855. static void    RecvReply();
  856.  
  857. static    struct sockaddr_in    remote;
  858. static    int            kdbxTimeout = 1;
  859. static    int            netSocket;
  860.  
  861.  
  862. /*
  863.  *----------------------------------------------------------------------
  864.  *
  865.  * CreateSocket --
  866.  *
  867.  *    Creates a UDP socket connected to the Sprite host's kernel 
  868.  *    debugger port.
  869.  *
  870.  * Results:
  871.  *    The stream ID of the socket.
  872.  *
  873.  * Side effects:
  874.  *    None.
  875.  *
  876.  *----------------------------------------------------------------------
  877.  */
  878. static int
  879. CreateSocket(spriteHostName)
  880.     char    *spriteHostName;
  881. {
  882.     int            socketID;
  883.     struct hostent     *hostPtr;
  884.  
  885.     hostPtr = gethostbyname(spriteHostName);
  886.     if (hostPtr == (struct hostent *) NULL) {
  887.     error("CreateSocket: unknown host %s\n", spriteHostName);
  888.     }
  889.     if (hostPtr->h_addrtype != AF_INET) {
  890.     error("CreateSocket: bad address type for host %s\n", 
  891.         spriteHostName);
  892.     }
  893.  
  894.     socketID = socket(AF_INET, SOCK_DGRAM, 0);
  895.     if (socketID < 0) {
  896.     perror_with_name("CreateSocket: socket");
  897.     }
  898.  
  899.     bzero((Address)&remote, sizeof(remote));
  900.     bcopy(hostPtr->h_addr, (Address)&remote.sin_addr, hostPtr->h_length);
  901.     remote.sin_port = htons(DBG_UDP_PORT);
  902.     remote.sin_family = AF_INET;
  903.  
  904.     if (connect(socketID, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
  905.     perror_with_name("CreateSocket: connect");
  906.     }
  907.  
  908.     return(socketID);
  909. }
  910.  
  911.  
  912. /*
  913.  * ----------------------------------------------------------------------------
  914.  *
  915.  *  StartDebugger --
  916.  *
  917.  *     Start off a new conversation with the debugger.
  918.  *
  919.  * Results:
  920.  *     None.
  921.  *
  922.  * Side effects:
  923.  *     Setup r network socket.
  924.  * ----------------------------------------------------------------------------
  925.  */
  926. static void
  927. StartDebugger()
  928. {
  929.         char    *host = hostName;
  930.     hostName = (char *) 0;
  931.     netSocket = CreateSocket(host);
  932.     hostName = host;
  933. }
  934.  
  935.  
  936. /*
  937.  * ----------------------------------------------------------------------------
  938.  *
  939.  *  SendRequest --
  940.  *
  941.  *     Send a request message to the kernel.
  942.  *
  943.  * Results:
  944.  *     None.
  945.  *
  946.  * Side effects:
  947.  *     None.
  948.  * ----------------------------------------------------------------------------
  949.  */
  950. static void
  951. SendRequest(numBytes, newRequest)
  952.     int        numBytes;
  953.     Boolean    newRequest;
  954. {
  955.      {
  956.     Dbg_Opcode    opcode;
  957.  
  958.     msgSize = numBytes;
  959.     if (newRequest) {
  960.         msgNum++;
  961.     }
  962.     *(int *)requestBuffer = msgNum;
  963.     bcopy(&msg, requestBuffer + 4, numBytes);
  964.     if (write(netSocket, requestBuffer, numBytes + 4) < numBytes + 4) {
  965.          MARK_DISCONNECTED;
  966.         perror_with_name("SendRequest: Couldn't write to the kernel socket\n");
  967.         return;
  968.     }
  969.     if (newRequest) {
  970.         opcode = (Dbg_Opcode) msg.opcode;
  971.         if (opcode == DBG_DETACH || opcode == DBG_CONTINUE ||
  972.         opcode == DBG_SINGLESTEP || opcode == DBG_DIVERT_SYSLOG || 
  973.         opcode == DBG_BEGIN_CALL || 
  974.         opcode == DBG_WRITE_REG || opcode == DBG_SET_PID) {
  975.         int    dummy;
  976.         /*
  977.          * Wait for explicit acknowledgments of these packets.
  978.          */
  979.         RecvReply(opcode, 4, &dummy, NULL, 1);
  980.         }
  981.     }
  982.     }
  983. }
  984.  
  985.  
  986. /*
  987.  * ----------------------------------------------------------------------------
  988.  *
  989.  *  RecvReply --
  990.  *
  991.  *     Receive a reply from the kernel.
  992.  *
  993.  * Results:
  994.  *     None.
  995.  *
  996.  * Side effects:
  997.  *     None.
  998.  * ----------------------------------------------------------------------------
  999.  */
  1000. static void
  1001. RecvReply(opcode, numBytes, destAddr, readStatusPtr, timeout)
  1002.     Dbg_Opcode    opcode;
  1003.     int        numBytes;
  1004.     char    *destAddr;
  1005.     int    *readStatusPtr;
  1006.     int    timeout;
  1007. {
  1008.     int        status;
  1009.     int     resendRequest = 0;
  1010.  
  1011.     if (numBytes + 8 > REPLY_BUFFER_SIZE) {
  1012.     fprintf(stderr,"numBytes <%d> > REPLY_BUFFER_SIZE <%d>\n",
  1013.             numBytes + 8, REPLY_BUFFER_SIZE);
  1014.     abort();
  1015.     }
  1016.      {
  1017.     int        readMask;
  1018.     struct    timeval    interval;
  1019.     int        bytesRead;
  1020.  
  1021.     interval.tv_sec = kdbxTimeout;
  1022.     interval.tv_usec = 0;
  1023.     do {
  1024.         if (timeout) {
  1025.         int    numTimeouts;
  1026.  
  1027.         numTimeouts = 0;
  1028.         /*
  1029.          * Loop timing out and sending packets until a new packet
  1030.          * has arrived.
  1031.          */
  1032.         do {
  1033.             if (!resendRequest) { 
  1034.             readMask = 1 << netSocket;
  1035.             status = select(32, &readMask, NULL, NULL, &interval);
  1036.             } else {
  1037.             status = 0;
  1038.             resendRequest = 0;
  1039.             }
  1040.             if (status == 1) {
  1041.             break;
  1042.             } else if (status == -1) {
  1043.                 MARK_DISCONNECTED;
  1044.             perror_with_name("RecvReply: Couldn't select on socket.\n");
  1045.             } else if (status == 0) {
  1046.             SendRequest(msgSize, 0);
  1047.             numTimeouts++;
  1048.             if (numTimeouts % 10 == 0) {
  1049.                 fprintf(stderr, 
  1050.                     "Timing out and resending to host %s\n",
  1051.                     hostName);
  1052.                 fflush(stderr);
  1053.                 QUIT;
  1054.             }
  1055.             }
  1056.         } while (1);
  1057.         }
  1058.         if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ ||
  1059.         opcode == DBG_GET_VERSION_STRING) {
  1060.         /*
  1061.          * Data and instruction reads return variable size packets.
  1062.          * The first two ints are message number and status.  If
  1063.          * the status is OK then the data follows.
  1064.          */
  1065.         immediate_quit++;
  1066.         bytesRead = read(netSocket, replyBuffer, numBytes + 8);
  1067.         immediate_quit--;
  1068.         if (bytesRead < 0) {
  1069.             MARK_DISCONNECTED;
  1070.             perror_with_name("RecvReply: Error reading socket.");
  1071.         }
  1072.         /*
  1073.          * Check message number before the size because this could
  1074.          * be an old packet.
  1075.          */
  1076.         if (*(int *)replyBuffer != msgNum) {
  1077.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1078.                 *(int *)replyBuffer, msgNum);
  1079.             fflush(stdout);
  1080.             resendRequest = 1;
  1081.             continue;
  1082.         }
  1083.         if (bytesRead == 8) {
  1084.             /*
  1085.              * Only 8 bytes so the read failed and there is no data.
  1086.              */
  1087.             *readStatusPtr = 0;
  1088.             return;
  1089.         }
  1090.             if (opcode == DBG_GET_VERSION_STRING) {
  1091.              strncpy(destAddr, (char *)(replyBuffer + 4),numBytes);
  1092.              return;
  1093.         }
  1094.         if (bytesRead != numBytes + 8) {
  1095.             printf("RecvReply: Short read (1): op=%d exp=%d read=%d",
  1096.                 opcode, numBytes + 4, bytesRead);
  1097.             continue;
  1098.         }
  1099.         *readStatusPtr = 1;
  1100.         bcopy(replyBuffer + 8, destAddr, numBytes);
  1101.         return;
  1102.         } else if (opcode == DBG_END_CALL) {
  1103.         int    length;
  1104.         /*
  1105.          * End call returns a variable size packet that contains
  1106.          * the result of the call. The format of the message is 
  1107.          * message number, length, data.
  1108.          */
  1109.         immediate_quit++;
  1110.         bytesRead = read(netSocket, replyBuffer, REPLY_BUFFER_SIZE);
  1111.         immediate_quit--;
  1112.         if (bytesRead < 0) {
  1113.             MARK_DISCONNECTED;
  1114.             perror_with_name("RecvReply: Error reading socket.");
  1115.         }
  1116.         /*
  1117.          * Check message number before the size because this could
  1118.          * be an old packet.
  1119.          */
  1120.         if (*(int *)replyBuffer != msgNum) {
  1121.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1122.                 *(int *)replyBuffer, msgNum);
  1123.             fflush(stdout);
  1124.             resendRequest = 1;
  1125.             continue;
  1126.         }
  1127.         length = *( int *)(replyBuffer + 4);
  1128.         if (bytesRead - 8 != length) {
  1129.             fprintf(stderr, "RecyReply: Short read for syslog data\n");
  1130.             fflush(stderr);
  1131.             length = bytesRead - 8;
  1132.         }
  1133.         if (length == 0) {
  1134.             /*
  1135.              * No data.
  1136.              */
  1137.             *readStatusPtr = 0;
  1138.             return;
  1139.         }
  1140.         /*
  1141.          * Dump out the buffer.
  1142.          */
  1143.         write(1, replyBuffer + 8, length);
  1144.         *readStatusPtr = 1;
  1145.         return;
  1146.         } else {
  1147.         /*
  1148.          * Normal request so just read in the message which includes
  1149.          * the message number.
  1150.          */
  1151.         immediate_quit++;
  1152.         bytesRead = read(netSocket, replyBuffer, numBytes + 4);
  1153.         immediate_quit--;
  1154.         if (bytesRead < 0) {
  1155.             MARK_DISCONNECTED;
  1156.             perror_with_name("RecvReply: Error reading socket (2).");
  1157.         }
  1158.         /*
  1159.          * Check message number before size because it could be
  1160.          * an old packet.
  1161.          */
  1162.         if (*(int *)replyBuffer != msgNum) {
  1163.             printf("RecvReply: Old message number = %d, expecting %d\n",
  1164.                 *(int *)replyBuffer, msgNum);
  1165.             fflush(stdout);
  1166.             resendRequest = 1;
  1167.             continue;
  1168.         }
  1169.         if (bytesRead != numBytes + 4) {
  1170.             printf("RecvReply: Short read (2): op=%d exp=%d read=%d",
  1171.                 opcode, numBytes + 4, bytesRead);
  1172.         }
  1173.         if (*(int *)replyBuffer != msgNum) {
  1174.             continue;
  1175.         }
  1176.         bcopy(replyBuffer + 4, destAddr, numBytes);
  1177.         return;
  1178.         }
  1179.     } while (1);
  1180.     }
  1181. }
  1182.  
  1183.  
  1184. /*
  1185.  * ----------------------------------------------------------------------------
  1186.  *
  1187.  *  WaitForKernel --
  1188.  *
  1189.  *      Wait for the kernel to send us a message to indicate that it is waiting
  1190.  *    to be debugged.
  1191.  *
  1192.  * Results:
  1193.  *     None.
  1194.  *
  1195.  * Side effects:
  1196.  *     None.
  1197.  * ----------------------------------------------------------------------------
  1198.  */
  1199. static void
  1200. WaitForKernel()
  1201. {
  1202.     int    dummy;
  1203.  
  1204.     RecvReply(DBG_CONTINUE, 4, &dummy, NULL, 0);
  1205. }
  1206.  
  1207.  
  1208. /*
  1209.  * ----------------------------------------------------------------------------
  1210.  *
  1211.  * BlockInCache --
  1212.  *
  1213.  *     See if the given block at the given address is in the cache.
  1214.  *
  1215.  * Results:
  1216.  *     1 if found block in cache, 0 if didn't.
  1217.  *
  1218.  * Side effects:
  1219.  *     None.
  1220.  */
  1221. static int
  1222. BlockInCache(blockNum, addr)
  1223.     int        blockNum;
  1224.     char    *addr;
  1225. {
  1226.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1227.     return((int) (cacheInfo[blockNum].version == currentVersion &&
  1228.        (unsigned int) cacheInfo[blockNum].realAddr == 
  1229.             ((unsigned int) (addr) & ~CACHE_BLOCK_OFFSET_MASK)));
  1230. }
  1231.  
  1232.  
  1233. /*
  1234.  * ----------------------------------------------------------------------------
  1235.  *
  1236.  * FetchBlock --
  1237.  *
  1238.  *     Fetch the given data block from the cache or the kernel if necessary.
  1239.  *
  1240.  * Results:
  1241.  *     1 if could fetch block into cache, 0 if couldn't.
  1242.  *
  1243.  * Side effects:
  1244.  *     Data cache modified.
  1245.  */
  1246. static int
  1247. FetchBlock(blockNum, srcAddr, opcode)
  1248.     int        blockNum;
  1249.     char    *srcAddr;
  1250.     Dbg_Opcode    opcode;
  1251. {
  1252.     int    successfulRead;
  1253.  
  1254.     blockNum = blockNum & CACHE_BLOCK_MASK;
  1255.     srcAddr = (char *) ((unsigned int) (srcAddr) & ~CACHE_BLOCK_OFFSET_MASK);
  1256.  
  1257.     if (BlockInCache(blockNum, srcAddr)) {
  1258.     return(1);
  1259.     }
  1260.     msg.opcode = opcode;
  1261.     msg.data.readMem.address = (int) srcAddr;
  1262.     msg.data.readMem.numBytes = cacheBlockSize;
  1263.     SendRequest(sizeof(msg.opcode) + sizeof(Dbg_ReadMem), 1);
  1264.     RecvReply(opcode, cacheBlockSize, 
  1265.         &dataCache[(unsigned int) (srcAddr) & CACHE_OFFSET_MASK],
  1266.         &successfulRead, 1);
  1267.     if (successfulRead) {
  1268.     cacheInfo[blockNum].version = currentVersion;
  1269.     cacheInfo[blockNum].realAddr = srcAddr;
  1270.     }
  1271.     return(successfulRead);
  1272. }
  1273.  
  1274.  
  1275.  
  1276. /*
  1277.  * ----------------------------------------------------------------------------
  1278.  *
  1279.  * Kdbx_Trace --
  1280.  *
  1281.  *     Write the trace command over to the kernel.  
  1282.  *
  1283.  * Results:
  1284.  *     None.
  1285.  *
  1286.  * Side effects:
  1287.  *     None.
  1288.  *
  1289.  * ----------------------------------------------------------------------------
  1290.  */
  1291. int 
  1292. Kdbx_Trace(opcode, srcAddr, destAddr, numBytes)
  1293.     Dbg_Opcode    opcode;        /* Which command */
  1294.     char    *srcAddr;    /* Where to read data from */
  1295.     char    *destAddr;    /* Where to write data to */
  1296.     int        numBytes;    /* The number of bytes to read or write */
  1297. {
  1298.     int            (*intrHandler)();
  1299.     int            i;
  1300.     int            retVal = 0;
  1301.  
  1302.     if (!initialized) {
  1303.     int    moreData;
  1304.     /*
  1305.      * Setup the cache and initiate a conversation with the other kernel.
  1306.      */
  1307.     if (cacheBlockSize == -1) {
  1308.          {
  1309.         cacheBlockSize = 256;
  1310.         cacheBlockShift = 8;
  1311.         }
  1312.     }
  1313.     dataCache = (char *) malloc(cacheSize);
  1314.     cacheInfo = (CacheInfo *) malloc(NUM_CACHE_BLOCKS * sizeof(CacheInfo));
  1315.     for (i = 0; i < NUM_CACHE_BLOCKS; i++) {
  1316.         cacheInfo[i].version = 0;
  1317.     }
  1318.     StartDebugger();
  1319.     /*
  1320.      * Dump the system log by faking a call command.
  1321.      */
  1322.     printf("Dumping system log ...\n");
  1323.     fflush(stdout);
  1324.     msg.opcode = (short)DBG_BEGIN_CALL;
  1325.     SendRequest(sizeof(msg.opcode), 1);
  1326.     msg.opcode = (short)DBG_END_CALL;
  1327.     do {
  1328.         SendRequest(sizeof(msg.opcode), 1);
  1329.         RecvReply(msg.opcode, 0, NULL, &moreData, 1);
  1330.     } while (moreData);
  1331.     initialized = 1;
  1332.     }
  1333.  
  1334.  
  1335.     if (opcode == DBG_DATA_READ || opcode == DBG_INST_READ) {
  1336.     int            firstBlock;
  1337.     int            lastBlock;
  1338.     unsigned    int    cacheOffset;
  1339.     int            toRead;
  1340.  
  1341.     /*
  1342.      * Read using the cache.
  1343.      */
  1344.     firstBlock = GET_CACHE_BLOCK(srcAddr); 
  1345.     lastBlock = GET_CACHE_BLOCK(srcAddr + numBytes - 1);
  1346.     for (i = firstBlock; i <= lastBlock; i++) {
  1347.         cacheOffset = ((unsigned int) srcAddr) & CACHE_OFFSET_MASK;
  1348.         if (i == lastBlock) {
  1349.         toRead = numBytes;
  1350.         } else if (i == firstBlock) {
  1351.         toRead = cacheBlockSize - 
  1352.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1353.         } else {
  1354.         toRead = cacheBlockSize;
  1355.         }
  1356.         if (!FetchBlock(i, srcAddr, opcode)) {
  1357.         return EIO;
  1358.         }
  1359.         bcopy(&dataCache[cacheOffset], destAddr, toRead);
  1360.         srcAddr += toRead;
  1361.         destAddr += toRead;
  1362.         numBytes -= toRead;
  1363.     }
  1364.     return(0);
  1365.     }
  1366.  
  1367.     if (opcode == DBG_DATA_WRITE || opcode == DBG_INST_WRITE) {
  1368.     int    firstBlock;
  1369.     int    lastBlock;
  1370.     int    cacheOffset;
  1371.     int    toWrite;
  1372.     char    *tSrcAddr;
  1373.     char    *tDestAddr;
  1374.     int    tNumBytes;
  1375.  
  1376.     /*
  1377.      * If the block that is being fetched is in the cache then write the
  1378.      * data there first before sending it over to the kernel.
  1379.      */
  1380.     tSrcAddr = srcAddr;
  1381.     tDestAddr = destAddr;
  1382.     tNumBytes = numBytes;
  1383.  
  1384.     firstBlock = GET_CACHE_BLOCK(destAddr); 
  1385.     lastBlock = GET_CACHE_BLOCK(destAddr + numBytes - 1);
  1386.     for (i = firstBlock; i <= lastBlock; i++) {
  1387.         cacheOffset = ((int) tDestAddr) & CACHE_OFFSET_MASK;
  1388.         if (i == lastBlock) {
  1389.         toWrite = tNumBytes;
  1390.         } else if (i == firstBlock) {
  1391.         toWrite = cacheBlockSize - 
  1392.                 (cacheOffset & CACHE_BLOCK_OFFSET_MASK);
  1393.         } else {
  1394.         toWrite = cacheBlockSize;
  1395.         }
  1396.         if (BlockInCache(i, tDestAddr)) {
  1397.         bcopy(tSrcAddr, &dataCache[cacheOffset], tNumBytes);
  1398.         }
  1399.         tSrcAddr += toWrite;
  1400.         tDestAddr += toWrite;
  1401.         tNumBytes -= toWrite;
  1402.     }
  1403.     }
  1404.  
  1405.     msg.opcode = (short) opcode;
  1406.  
  1407.     /*
  1408.      * Do the rest of the work for the desired operation.
  1409.      */
  1410.  
  1411.     switch (opcode) {
  1412.  
  1413.     /*
  1414.      * For these operations the desired data is read from the other
  1415.      * kernel and stored at destAddr.
  1416.      */
  1417.     case DBG_READ_ALL_REGS:
  1418.     case DBG_GET_STOP_INFO:
  1419.         SendRequest(sizeof(msg.opcode), 1);
  1420.         RecvReply(opcode, numBytes, destAddr, NULL, 1);
  1421.         break;
  1422.  
  1423.     /*
  1424.      * For this operation the desired data is read from srcAddr
  1425.      * and written to the other kernel.
  1426.      */
  1427.     case DBG_SET_PID:
  1428.         msg.data.pid = *(int *)srcAddr;
  1429.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pid), 1);
  1430.         break;
  1431.  
  1432.     /*
  1433.      * When writing a general purpose register first the address to write
  1434.      * that is stored in destAddr must be given to the other kernel.
  1435.      * Then the data itself which is stored at srcAddr can be written over.
  1436.      */
  1437.     case DBG_WRITE_REG:
  1438.         msg.data.writeReg.regNum = (int) destAddr;
  1439.         msg.data.writeReg.regVal = *(int *) srcAddr;
  1440.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_WriteReg), 1);
  1441.         break;
  1442.  
  1443.     /*
  1444.      * When writing to the kernels instruction or data space first the
  1445.      * address of where to write to (destAddr) and then the number of
  1446.      * bytes to write (numBytes) must be sent over.  Finally all of
  1447.      * the data is read from srcAddr and written over.
  1448.      */
  1449.  
  1450.     case DBG_INST_WRITE:
  1451.     case DBG_DATA_WRITE: {
  1452.         char    writeStatus;
  1453.  
  1454.         msg.data.writeMem.address = (int) destAddr;
  1455.         msg.data.writeMem.numBytes = numBytes;
  1456.         bcopy(srcAddr, msg.data.writeMem.buffer, numBytes);
  1457.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1458.         RecvReply(opcode, 1, &writeStatus, NULL, 1);
  1459.         if (writeStatus == 0) {
  1460.         retVal = EIO;
  1461.         fprintf(stderr, "ERROR: invalid write address 0x%x\n",destAddr);
  1462.         } 
  1463.         break;
  1464.     }
  1465.     case DBG_DIVERT_SYSLOG:
  1466.         msg.data.syslogCmd = (Dbg_SyslogCmd)srcAddr;
  1467.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1468.         break;
  1469.     case DBG_BEGIN_CALL:
  1470.         SendRequest(sizeof(msg.opcode), 1);
  1471.         break;
  1472.     case DBG_END_CALL: {
  1473.         Boolean    moreData;
  1474.         do {
  1475.         SendRequest(sizeof(msg.opcode), 1);
  1476.         RecvReply(opcode, 0, NULL, &moreData, 1);
  1477.         } while (moreData);
  1478.         break;
  1479.     }
  1480.  
  1481.     case DBG_DETACH: {
  1482.         msg.opcode = (short) DBG_DIVERT_SYSLOG;
  1483.         msg.data.syslogCmd = DBG_SYSLOG_TO_ORIG;
  1484.         SendRequest(sizeof(msg.opcode) + sizeof(Dbg_SyslogCmd), 1);
  1485.  
  1486.         msg.opcode = (short) DBG_DETACH;
  1487.         msg.data.pc = *(int *) srcAddr;
  1488.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1489.         break;
  1490.     }
  1491.  
  1492.     case DBG_CONTINUE:
  1493.     case DBG_SINGLESTEP:
  1494.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc), 1);
  1495.         currentVersion++;
  1496.         WaitForKernel();
  1497.         break;
  1498.  
  1499.     case DBG_CALL_FUNCTION: {
  1500.         int        returnValue;
  1501.  
  1502.         msg.data.callFunc.address = (int) destAddr;
  1503.         msg.data.callFunc.numBytes = numBytes;
  1504.         bcopy(srcAddr, msg.data.callFunc.buffer, numBytes);
  1505.         SendRequest(sizeof(msg.opcode) + 2 * sizeof(int) + numBytes, 1);
  1506.         RecvReply(opcode, sizeof(returnValue), &returnValue, NULL, 1);
  1507.         return (returnValue);
  1508.     }
  1509.     case DBG_REBOOT: {
  1510.         msg.data.reboot.stringLength = numBytes;
  1511.         bcopy(srcAddr, msg.data.reboot.string, numBytes);
  1512.         SendRequest(sizeof(msg.opcode) + sizeof(int) + numBytes, 1);
  1513.         return (0);
  1514.     }
  1515.     case DBG_GET_VERSION_STRING: {
  1516.         SendRequest(sizeof(msg.opcode), 1);
  1517.         RecvReply(opcode,numBytes , destAddr, NULL, 1);
  1518.         return (0);
  1519.     }
  1520.     default:
  1521.         printf("Unknown opcode %d\n", opcode);
  1522.         return(-1);
  1523.     }
  1524.     return(retVal);
  1525. }
  1526. remote_close()
  1527. {
  1528. }
  1529. remote_clean_up()
  1530. {
  1531.     MARK_DISCONNECTED;
  1532. }
  1533.  
  1534.  
  1535. read_kmem(memaddr, myaddr, len)
  1536.     char *memaddr;
  1537.     char *myaddr;
  1538.     int      len;
  1539. {
  1540.     static int fd = -1;
  1541.     int count;
  1542.  
  1543.     if (fd < 0) { 
  1544.     char template[100];
  1545.     /*
  1546.      * Open a temp file to write counters to. We unlink the file so it will
  1547.      * disappear when we exit.
  1548.      */
  1549.     strcpy(template, "/tmp/kgdbXXXXXXXX");
  1550.     fd = mkstemp(template);
  1551.     if (fd < 0) {
  1552.         error("open kmem tmp file");
  1553.     }
  1554.     (void) unlink(template);
  1555.     }
  1556.     if (lseek(fd, 0, L_SET) < 0) {
  1557.     error("lseek kmem file");
  1558.     }
  1559.     count = write(fd, memaddr, len);
  1560.     if (count != len) {
  1561.     return EIO;
  1562.     }
  1563.  
  1564.     /*
  1565.      * Rewind the file and read the counters from it.
  1566.      */
  1567.     count = lseek(fd, 0, L_SET);
  1568.     if (count >= 0) {
  1569.         count = read(fd, myaddr, len);
  1570.     }
  1571.     if (count != len) {
  1572.     return EIO;
  1573.     }
  1574.     return 0;
  1575. }
  1576.  
  1577.  
  1578.